#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>

#define MAX 1024 // 指令最大长度
#define N 64  // 获取正确指令的最大个数

int split(char* commandstr[], char* argv[])
{
	assert(commandstr);
	assert(argv);
	argv[0] = strtok(commandstr, " ");
	if( argv[0] == NULL ) return 0;
	int i = 1;
	while(1)
	{
		argv[i] = strtok(NULL, " "); 
		if(argv[i] == NULL) break;
		i++;
	}
	return 1;
}
void DebugPrint(char* argv[])
{
	int i = 0;
	for(; argv[i]; ++i)
	printf("%d:%s\n", i, argv[i]);
}
int main()
{
	extern char** environ; // 系统环境变量表
	int exit_code = 0; // 退出码
	char myenv[32][128]; // 自定义环境变量表
	int index = 0; // 环境变量下标
	while(1)
	{
		char commandstr[MAX] = {0}; // 用于接受指令的数组
		char* argv[N] = {NULL}; // 用于接受正确指令的指针数组
		printf("[mybash]$: ");
		char* s = fgets(commandstr, sizeof(commandstr), stdin); // 接受数据
		assert(s != NULL);
		(void)s; // 用于消除release版本下的警告
		commandstr[strlen(commandstr)-1] = 0; // 消除最后一个录入的\n
		//printf("%s\n", commandstr);
		///////////////  以上是第一步   //////////////////

		int n = split(commandstr, argv);  // 用于特定方式分割字符串的函数，按空格分割
		//if(n)
		//DebugPrint(argv);
		//////////////   以上是第二步   /////////////////

		//---------------------------    更新    -----------------------------
		//########  ls更新颜色  ##########
		if(strcmp(argv[0], "ls") == 0)
		{
			int pos = 1;
			while(argv[pos] != NULL)
			{
				pos++;
			}
			argv[pos++] = (char*)"--color=auto";
			argv[pos] = NULL;
		}
		//########  内置/内建命令  ###########
		if(strcmp(argv[0], "echo") == 0)
		{
			if(argv[1][0] == '$')
			{
				if(argv[1][1] == '?')
					printf("%d\n",exit_code);
				else
				{
					const char* env = getenv( argv[1] + 1 );
					if(env != NULL)
					printf("%s=%s\n", argv[1]+1, env);
				}
			}
			continue;
		}
		else if(strcmp(argv[0], "cd") == 0)
		{
			chdir(argv[1]); // 改变路径的函数
			continue;
		}
		else if(strcmp(argv[0], "export") == 0)
		{
			strcpy(myenv[index], argv[1]);  // 新起一个指针数组来存储环境变量
			putenv(myenv[index++]);  // 导入环境变量
			continue;
		}
		else if(strcmp(argv[0], "env") == 0)
		{
			int i = 0;
			for(;environ[i]; ++i)
			printf("%d->%s\n", i, environ[i]);
			continue;
		}	
		//----------------------------------------------
		int pid = fork();
		if(pid == 0)
		{
			execvp(argv[0], argv); // 将输入的指令交给系统调用执行
			exit(0);
		}
		int status = 0;
		waitpid(pid, &status, 0);  // 父进程回收资源
		exit_code = WEXITSTATUS(status);
		//////////////   以上是最终步  /////////////////
	}
	return 0;
}
